Vi (pronounced "vee-eye") is a popular and very powerful text editor. It's fairly hard to learn, but it's well worth learning, especially since it's often the only editor available on an unfamiliar Unix system.
The first thing you'll notice about vi when you run it is that you can't enter text straight away. This is because vi starts in command mode, which uses many commands based on keys that would normally produce a character (such as letters and punctuation). This is an unusual approach but it works well as the majority of commands are single, unshifted keystrokes on the main part of the keyboard, meaning that for the vast majority of your time using vi, your hands stay in exactly the same place. This way you don't waste time moving your hands around the keyboard. Also, the rarity of commands using CTRL or ALT reduces the amount of stretching that the hand has to do, reducing the probability of repetitive strain injury.
Modes
Vi has several modes; the most important are command mode, insert mode, command line mode and visual mode. In any of these modes you can press ESC to go back to command mode.
Insert mode
Insert mode behaves much as you'd expect: pressing a key inserts the appropriate character. You can use the arrow keys to move about, but bear in mind that going back to command mode is often faster, especially if you have a long way to move.
There are several ways to enter insert mode from command mode. Most commonly you will press i to start typing before the cursor, or a to start typing after it. You can also press o or O to insert a blank line respectively after or before the current one and start typing in it. (Note that vi is case sensitive.)
To leave insert mode, just press ESC.
Command mode
Most of your time will be spent in command mode. Here you enter commands to enter other modes, move the cursor around, and do simple text manipulation such as deleting (cutting), yanking (copying) and pasting.
In general, there are two types of command: those that are modified using a count, and those that are modified using a movement. Commands taking a count can be entered without one, but commands taking a movement don't do anything until they get a movement telling them how much text to act on.
As an exanple, there are two ways to delete 5 lines, and to delete 10 characters to the right of the cursor.
Supplying a count
To delete the current line and the four lines after it, press 5dd. Similarly, to delete the current character and 9 characters to the right of it, press 10x.
The exact meaning of the count depends on the command. For example, the K command looks up the word under the cursor in the manual (exactly as if you had typed man (word) in the shell). Adding a count tells the command to look the word up in that section of the manual (exactly as if you had typed man (count) (word) in the shell).
Combining a command with a movement
Movement of the cursor is achieved using the keys h, j, k and l - these are left, down, up and right respectively. Think of the curve in the j as being an arrow pointing downwards. These are "count" commands - that is, they can be repeated by typing a number before it. You can also move the cursor using the arrow keys, but they can't be combined with commands as described below like hjkl can. There are also lots of advanced movement commands that move further, e.g. to the beginning / end of the word / sentence / paragraph. These are documented in vim's online help system (type :h to read it).
To delete the current line and the 4 lines after it, press d4j. In words, this means "delete lines from here until wherever the movement 4j goes". Similarly, d9l deletes the current character and the 9 characters to the right of it - it says "delete characters from here until wherever the movement 9l goes".
Command mode reference
Command | Meaining | Modifier |
a | Append text after cursor (enters insert mode) | Count |
d | Delete (cut) text | Movement |
dd | Delete line | Count |
D | Delete rest of line (if given count > 1, also deletes count-1 following lines) | Count |
gg | Move to start of file (or countth line) | Count |
G | Move to end of file (or countth line) | Count |
h | Move left | Count |
i | Insert text before cursor (enters insert mode) | Count |
j | Move down | Count |
J | Join lines (minimum count 2, if specified) | Count |
k | Move up | Count |
l | Move right | Count |
n | Repeat last search | Count |
o | Insert text in a blank line after current line (enters insert mode) | Count |
O | Insert text in a blank line before current line (enters insert mode) | Count |
p | Paste after cursor | Count |
P | Paste before cursor | Count |
u | Undo (very useful!) | Count |
CTRL-r | Redo | Count |
v | Enter visual mode | Movement |
V | Enter linewise visual mode | Movement |
x | Delete character at cursor | Count |
X | Delete character before cursor | Count |
y | Yank (copy) | Movement |
yy | Yank line | Count |
/ | Search forwards from cursor | Count |
? | Search backwards from cursor | Count |
: | Enter command-line mode | Count or Visual |
< | Shift line left count times | Count |
> | Shift line right count times | Count |
<< | Shift line left once | None |
>> | Shift line right once | None |
% | Match brackets / braces etc (handy if you get lost among lots of parentheses) | None |
^ | Move to start of line (but after whitespace) | None |
0 | Move to start of line | None |
$ | Move to end of line | None |
Command line mode
Vi has a "command line" which is used to enter a number of "Ex commands" that have long names or take various textual arguments - for example, opening and saving files and setting variables. To enter an Ex command first press : (colon). There isn't much to say about this mode except to give a list of some commonly used commands.
Command | Meaning |
e | Open a new file for editing - follow by filename |
w | Save (write) - follow by filename to use (unless you want to save with the same filename) |
q | Quit |
wq | Save and quit |
noh | Stop highlighting things found by the last search |
syntax on | Turn syntax colouring on (vim-specific) |
syntax off | Turn syntax colouring off (vim-specific) |
set | Set an option |
let | Set a variable |
s/foo/bar/ | Substitute regular expression foo with bar. Useful for changing large amounts of text at the same time or in the same way |
h | Read vim's online help - optionally follow by a word to look up. (vim-specific, though probably works in some other versions) |
Sometimes it might be a bad idea to execute a command - for example, typing :q without saving first. In these cases vi might not let the command go ahead. You can override this using an exclamation mark; for example, :q! quits without saving, even if the buffer has changed since you last saved.
For commands that act on the current line only, the command can be preceded by % to make it act on every line instead. There are a few such range modifiers, all of which are documented in vim's online help.
Visual mode
This provides a convenient alternative to most movement-oriented commands rather like selection in other editors. Pressing v starts a highlight on the current character that can be expanded by moving about (with hjkl or other movement commands, but not the arrow keys). Similarly, pressing V selects text a line at a time, and moving up and down changes the amount of text selected.
For example, v9ld will delete the current character and the 9 to the right of it, but, equivalently, you can press v, then l nine times, followed by d. And V4jd, or V followed by j four times and then d, will delete the current line and the four lines after it. Between the v or V and the command, the text which the command will act on is highlighted.
To cancel visual mode, press ESC.
(Historical note: vi is an abbreviation for "visual", but it wasn't named after this mode - rather, it was to distinguish it from line editors such as ed which were the only editors available when the original vi was created back in the early 1970s. They're not much used now because the hardcopy terminals they were designed for are long since obsolete.)
Ex mode
Ex mode is like command-line mode, except that you enter a sequence of Ex commands instead of directly working on the file. It's rather like ed. As such it is rather hard to use and not particularly useful.
Some useful features in vim
The following instructions refer only to vim; other clones may have similar mechanisms, but probably not the same ones.
Syntax colouring
Many clones of vi, including vim, provide highlighting of syntactic elements in a large number of programming and markup languages. This can greatly help in understanding the structure of code, especially if you are dyslexic.
To turn on syntax highlighting, type :syntax on. If you are using an appropriate filename (i.e. one that has the canonical extention for the language you are editing) vim will be able to guess which language you want. in some cases the guess is wrong - in these cases you can tell vim to highlight for a different language by typing :set syntax=(language).
In particular, the filename extension .pl is, by default, associated with Perl. Unfortunately this clashes with the default extension for Prolog source files, which is also .pl. You can tell vim to interpret the file as Prolog by typing :set syntax=prolog.
Another thing to watch out for is that each syntax specification may support several dialects. For example, vim's Pascal highlighting supports GNU Pascal as well as Delphi. Generally you need to set a variable to change vim's behaviour in these cases:
- To highlight Pascal using Delphi's dialect, type :let pascal_delphi = 1
- To highlight Bourne shell scripts using the bash dialect, type :let is_bash = 1
Autoindent and c-indent
These are two exceptionally handy features when editing source code:
- Autoindent (turned on with :set ai and turned off with :set noai) automatically inserts as much whitespace at the start of a new line as there is on the current line (e.g. when you press enter or use the o or O commands). This saves you reaching for the tab key most of the time.
- C-indent (turned on with :set cin and turned off with :set nocin) provides even more when editing C source code (and source code for languages with C-like syntax, such as Java). On top of the provisions of autoindent, it automatically inserts extra whitespace where appropriate, particularly after a {, and deletes it when appropriate, particularly when you type a }. With both options turned on, you almost never have to press the tab key, saving a lot of time.
Note: When pasting text into vim using the middle mouse button under X, autoindent and cindent can easily mess up the formatting of the text being pasted. You should turn both options off before pasting.
Folds
Many of the editors supplied with integrated development environments (IDEs) allow you to collapse large sections of code, such as a class, function, or loop body. Folds achieve the same effect in vim.
In C-like languages, a convenient way to fold all {} blocks is to do:
:syn region myFold start="{" end="}" transparent fold
:syn sync fromstart
:set foldmethod=syntax
This will automatically fold all {} blocks. To expand the fold under the cursor, press za, and the same to close it again. To manually create a fold, use the zf command with a movement or Visual mode selection.